package se.webbzon.boltzmann.game.event;

import java.util.ArrayList;

import se.webbzon.boltzmann.battle.factory.property.PlayerBPF;
import se.webbzon.boltzmann.battle.group.BattleGroup;
import se.webbzon.boltzmann.battle.object.npc.BattleNPC;
import se.webbzon.boltzmann.battle.property.BattlePropertyFactory;
import se.webbzon.boltzmann.battle.round.BattleRound;
import se.webbzon.boltzmann.battle.round.BattleRoundListener;
import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.boltzmann.effect.Effect;
import se.webbzon.boltzmann.effect.ScreenTransitionEffect;
import se.webbzon.boltzmann.game.character.CharacterException;
import se.webbzon.boltzmann.game.environment.GameEnvironment;
import se.webbzon.boltzmann.game.object.npc.HostileNPC;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.sequence.Sequence;
import se.webbzon.boltzmann.game.sequence.Sequences;
import se.webbzon.boltzmann.game.sequence.builder.SoftSequenceBinding;
import se.webbzon.boltzmann.timer.Timer;
import se.webbzon.boltzmann.timer.TimerListener;
import se.webbzon.boltzmann.world.BattleWorldLoader;
import se.webbzon.boltzmann.world.WorldLoaderException;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldobject.WorldObject;

public class StartBattleEvent extends AbstractGameEvent {
	
	// The sequence associated with this battle event
	private final Sequence sequence;
	
	// The binding of this event
	private final WorldObject binding;
	
	// A timer listener
	private final TimerListener timerListener;
	
	// A battle round listener
	private final BattleRoundListener battleRoundListener;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public StartBattleEvent(Sequence sequence, WorldObject binding, String[] arguments) {
		super(arguments);
		this.sequence = sequence;
		this.binding = binding;
		timerListener = new TimerListenerImpl();
		battleRoundListener = new BattleRoundListenerImpl();
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override protected void onBegin(WorldArea world) {
		Effect transition = new ScreenTransitionEffect(	
						ScreenTransitionEffect.CLOCKWISE + 
						ScreenTransitionEffect.HORIZONTAL + 
						ScreenTransitionEffect.VERTICAL,
						2,0.5,"transition_star",30);
		transition.launch(world);
		Timer timer = new Timer(30);
		timer.addListener(timerListener);
		timer.start(world);
	}

	@Override protected void onEnd() {};
	
	/*============================================================
	Private Classes
	============================================================*/
	
	private final class TimerListenerImpl implements TimerListener {

		@Override public void onAlarm(Timer timer, WorldArea world) {
			if (binding instanceof HostileNPC) try {
				GameEnvironment genv = (GameEnvironment) sequence.getEnvironment();
				HostileNPC npc = (HostileNPC) binding;
				AbstractPlayerCharacter player = (AbstractPlayerCharacter) sequence.getBinding(SoftSequenceBinding.PLAYER);
				ArrayList<BattleGroup> battleGroups = new ArrayList<BattleGroup>();
				
				// Add the player to the battle
				BattleGroup friendlyGroup = new BattleGroup(0,0);
				BattlePropertyFactory spf = new PlayerBPF(genv.getBattleEnvironment(),player.getPlayer());
				friendlyGroup.addParticipant(new BattleNPC(spf.makeNew(null),friendlyGroup));
				battleGroups.add(friendlyGroup);

				// Add all the enemies to the battle
				BattleGroup hostileGroup = new BattleGroup(1,1);
				for (BattlePropertyFactory factory : npc.getBattlePropertyFactories()) {
					hostileGroup.addParticipant(
							new BattleNPC(factory.makeNew(null),hostileGroup));
				}
				battleGroups.add(hostileGroup);

				// Add a listener used return to the game world
				final ArrayList<BattleRoundListener> listeners = 
						new ArrayList<BattleRoundListener>();
				listeners.add(battleRoundListener);

				// Load the battle
				final BattleWorldLoader loader = new BattleWorldLoader(genv.getBattleEnvironment(),getArgument(0),player.getPlayer(),battleGroups,listeners);
				final WorldArea battleWorld = loader.load();

				world.gotoWorldArea(battleWorld);
			} catch (CharacterException | WorldLoaderException e) {
				Debug.report(e);
			} else
				throw new GameEventException("binding is not an instance of HostileNPC.");
		}

	}
	
	private final class BattleRoundListenerImpl implements BattleRoundListener {

		@Override public void roundStart(BattleRound battleRound) {};

		@Override public void roundComplete(BattleRound battleRound) {};

		@Override public void groupStart(BattleRound battleRound, BattleGroup group) {};

		@Override public void groupComplete(BattleRound battleRound, BattleGroup group) {};

		@Override public void turnStart(BattleRound battleRound, BattleNPC participant) {};

		@Override public void turnComplete(BattleRound battleRound, BattleNPC participant) {};

		@Override public void battleStart(BattleRound battleRound, WorldArea world) {};

		@Override public void battleComplete(BattleRound battleRound, int factionId) {
			Sequences.set(sequence, getArgument(1), factionId == 0 ? 1.0 : 0);
			end();
		}
		
	}

}
